import MessageError from "@/errors/MessageError";
import Reflect from "@/utils/reflect";
// import { ElMessage } from "element-plus";
import { AnyFunc } from "./type";

export type ErrorResetFunc = (this: any, error: Error) => any;

export type ErrorPostFunc = (this: any, error: Error) => any;

export type ErrorMessageFunc = (this: any, errorMessage: string | null) => any;

interface PropertyFuncs<F> {
  propertyKey: string;
  valueFunc: F;
}

export function ErrorReset(phase: string, valueFunc: any) {
  return function<
    T extends { [key in K]: any },
    K extends string,
  > (target: T, propertyKey: K) {
    Reflect.pushValue(target, ["ErrorReset", phase || ""], { propertyKey, valueFunc } as PropertyFuncs<ErrorResetFunc>);
  }
}

export function ErrorMessage(phase: string, valueFunc: ErrorMessageFunc) {
  return function<
    T extends { [key in K]: any },
    K extends string,
  > (target: T, propertyKey: K) {
    Reflect.pushValue(target, ["ErrorMessage", phase || ""], { propertyKey, valueFunc } as PropertyFuncs<ErrorMessageFunc>);
  }
}

export function ErrorPost(phase: string) {
  return function(target: any, propertyKey: string, descriptor: TypedPropertyDescriptor<ErrorPostFunc>) {
    Reflect.pushValue(target, ["ErrorPost", phase || ""], propertyKey);
  }
}

export function ErrorIntercept(...phases: string[]) {
  return function(target: any, propertyKey: string, descriptor: TypedPropertyDescriptor<AnyFunc>) {
    Reflect.setValue(target, ["ErrorIntercept", propertyKey], descriptor.value);
    descriptor.value = async function(...args) {
      const instance: any = this;
      phases = phases.length === 0 ? [""] : phases;
      try {
        await Reflect.getValue<AnyFunc>(target, ["ErrorIntercept", propertyKey]).call(this, ...args);
        // 清空异常信息
        for (const phase of phases) {
          Reflect.forEachValue<PropertyFuncs<ErrorMessageFunc>>(target, ["ErrorMessage", phase], [], ({ propertyKey, valueFunc }) => {
            instance[propertyKey] = typeof valueFunc === "function" ? valueFunc(null) : valueFunc;
          });
        }
      } catch (error) {
        if (error instanceof MessageError) {
          // 弹出提示信息
          alert(`${error.message}`);
          // ElMessage.warning(`${error.message}`);
        }
        // 异常信息
        if (error instanceof Error) {
          for (const phase of phases) {
            Reflect.forEachValue<PropertyFuncs<ErrorMessageFunc>>(target, ["ErrorMessage", phase], [], ({ propertyKey, valueFunc }) => {
              instance[propertyKey] = typeof valueFunc === "function" ? valueFunc(error.message) : valueFunc;
            });
          }
        }
        // 异常后置触发
        for (const phase of phases) {
          Reflect.forEachValue<string>(target, ["ErrorPost", phase], [], (postFuncProperty) => {
            instance[postFuncProperty](error);
          });
        }
      }
    }
  }
}
